/*
 * Copyright (c) 2006-2021, Halo team
 *
 * SPDX-License-Identifier: GPLv3
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-09-11     Eywen        the first version
 */

#include "extruder_step.h"
#include "common.h"

static float extruder_step_speed_to_freq(float speed,
                                         extruder_step_type_t step_type);
static float extruder_step_capacity_to_pulse(float distance,
                                             extruder_step_type_t step_type);
static float extruder_step_pulse_to_capacity(uint32_t pulse,
                                             extruder_step_type_t step_type);
static bool extruder_step_add_task(extruder_step_t *device,
                                   extruder_step_task_t *task);
static void extruder_step_forward_level_set(extruder_step_t *step, bool level);
static inline void extruder_step_axis_range_set(extruder_step_t *step,
                                                float axis_length);
static inline void extruder_step_axis_zero_offset_set(extruder_step_t *step,
                                                      float offset);

/* 初始化挤出机的一些参数 */
bool extruder_step_init(extruder_step_t *device, extruder_step_type_t type,
                      smart_step_id_t id ,int pin_pwm, int pin_en, int pin_dir,
                      uint32_t timer_freq)
{
    ASSERT_NULL(device);
    ASSERT_NULL(device->step_drv);

    smart_step_t *smart_step;
    bool ret;
    device->type = type;

    smart_step = device->step_drv;
    ret = smart_step->ops->init(smart_step, pin_pwm, pin_en, pin_dir, timer_freq, id);
    if(ret == false){
        goto  err;
    }

    return true;
err:
    return false;
}

/* 流量转换成脉冲个数 */
inline float extruder_step_capacity_to_pulse(float distance,
                                             extruder_step_type_t step_type)
{
    UNUSED(step_type);
    return distance;
}

/* 脉冲数转换成距离流量 */
inline float extruder_step_pulse_to_capacity(uint32_t pulse,
                                             extruder_step_type_t step_type)
{
    UNUSED(step_type);
    return (float)pulse;
}


/* 将步进电机移动的速度转换成驱动的频率 */
float extruder_step_speed_to_freq(float speed, extruder_step_type_t step_type)
{
    UNUSED(step_type);
    return speed;
}

/* 获取当前电机的错误状态 */
extruder_step_err_t extruder_step_error_get(extruder_step_t *device)
{
    return device->err_status;
}

/* 将需要移动目标距离和速度送入到地层的驱动任务队列*/
bool  extruder_step_add_task(extruder_step_t *device, extruder_step_task_t *task)
{
    ASSERT_NULL(device);
    smart_step_t *step;
    smart_step_task_t pwm_task;
    step = device->step_drv;
    pwm_task.freq = extruder_step_speed_to_freq(task->speed, device->type);
    pwm_task.pulse = extruder_step_capacity_to_pulse(task->capacity, device->type);

    return step->ops->add_task(step, &pwm_task);
}

/* 设置电机能转动的最大长度 */
inline void extruder_step_axis_range_set(extruder_step_t *step, float axis_length)
{
    ASSERT_NULL(step);
    step->axis_length = axis_length;
}

/* 设置home地址的偏移值 */
inline void extruder_step_axis_zero_offset_set(extruder_step_t *step, float offset)
{
    ASSERT_NULL(step);

    step->home_offset = offset;
}

/* 获取当前位置(相对于home地址,非绝对的0位置) */
 float extruder_step_axis_coordinate(extruder_step_t *step)
 {
     uint32_t pulse;
     float abs_loc;
     smart_step_t *smart_step;
     smart_step = step->step_drv;
     pulse = smart_step->ops->pulse(smart_step);
     abs_loc = extruder_step_pulse_to_capacity(pulse, step->type);
     return (abs_loc - step->home_offset);
 }

/* 设置电机争相转动方向的标准电平 */
inline void extruder_step_forward_level_set(extruder_step_t *step, bool level)
{
    ASSERT_NULL(step);
    smart_step_t *smart_step;
    smart_step = step->step_drv;
    smart_step->ops->forward_level_set(smart_step, level);
}

static bool extruder_step_task_start(extruder_step_t *step)
{
    ASSERT_NULL(step);
    step->step_drv->ops->start(step->step_drv);
    return true;
}

static bool extruder_step_task_full(extruder_step_t *step)
{
    return step->step_drv->ops->task_is_full(step->step_drv);
}

static bool extruder_step_task_empty(extruder_step_t *step)
{
    return step->step_drv->ops->task_is_empty(step->step_drv);
}


const static extruder_step_ops_t s_extruder_step_ops = {
    .init = extruder_step_init,
    .add_task = extruder_step_add_task,
    .error = extruder_step_error_get,
    .start_task = extruder_step_task_start,
    .axis_range_set = extruder_step_axis_range_set,
    .axis_zero_offset_set = extruder_step_axis_zero_offset_set,
    .coordinate = extruder_step_axis_coordinate,
    .forward_level_set = extruder_step_forward_level_set,
    .task_full = extruder_step_task_full,
    .task_empty = extruder_step_task_empty,
};

bool extruder_step_register(extruder_step_t *device)
{
    ASSERT_NULL(device);
    smart_step_t *smart_step;

    device->ops = (extruder_step_ops_t *)&(s_extruder_step_ops);

    device->step_drv = MEM_MALLOC(sizeof (smart_step_t));
    if(device->step_drv == NULL){
        debug_error("Insufficient system memory");
        goto err;
    }

    smart_step = device->step_drv;
    if(false == smart_step_register(smart_step)){
        goto err;
    }

    return true;
err:
    /* 初始化出错, 释放申请的内存*/

    if(device->step_drv){
        MEM_FREE(device->step_drv);
        device->step_drv = NULL;
    }
    return false;
}

